#include <modules\graphics\opengl\opengl_shader_effect.h>

namespace DelGE
{
	namespace Modules
	{
		namespace Graphics
		{
			OpenGLShaderEffect::OpenGLShaderEffect()
			{
				this->mUniformMap = map<string, int>();
				this->iProgramID = glCreateProgram();
			}

			OpenGLShaderEffect::~OpenGLShaderEffect()
			{
				this->mUniformMap.clear();
				glDeleteProgram(this->iProgramID);
			}

			OpenGLShaderEffect *OpenGLShaderEffect::CreateShaderEffect()
			{
				return new OpenGLShaderEffect();
			}

			void OpenGLShaderEffect::AttachShader(OpenGLShader *pShader)
			{
				glAttachShader(this->iProgramID, pShader->GetShaderID());
			}

			void OpenGLShaderEffect::DetachShader(OpenGLShader *pShader)
			{
				glDetachShader(this->iProgramID, pShader->GetShaderID());
			}

			void OpenGLShaderEffect::Link()
			{
				glLinkProgram(this->iProgramID);
			}

			int OpenGLShaderEffect::GetProgramID()
			{
				return this->iProgramID;
			}

			void OpenGLShaderEffect::SetUniform_Integer(string sName, int iValue)
			{
				glUniform1i(this->GetGLUniformLocation(sName), iValue);
			}

			void OpenGLShaderEffect::SetUniform_Float(string sName, float fValue)
			{
				glUniform1f(this->GetGLUniformLocation(sName), fValue);
			}

			void OpenGLShaderEffect::SetUniform_Vector(string sName, const Vector3 &rVector)
			{
				glUniform3f(this->GetGLUniformLocation(sName), rVector.x, rVector.y, rVector.z);
			}
			
			void OpenGLShaderEffect::SetUniform_Matrix(string sName, const Matrix &rMatrix)
			{
				glUniformMatrix4fv(this->GetGLUniformLocation(sName), 1, 0, rMatrix.fData);
			}

			int OpenGLShaderEffect::GetGLUniformLocation(string sName)
			{
				if (this->mUniformMap.lower_bound(sName) == this->mUniformMap.end())
					this->mUniformMap[sName] = glGetUniformLocation(this->iProgramID, sName.c_str());

				return this->mUniformMap[sName];
			}
		}
	}
}